const zbActionSheet = function(instance){
    this.instance = instance;
    this.onConfirm = null; //点击确认后执行回调
    this.isConfirm = 0; //是否已点击过确认按钮, 防止频繁点击

    this.init = function (title='') {
        this.initCss();
        this.initTpl();
        document.getElementById('zbASTitle').innerText = title;
    }

    //浮层模板
    this.tpl = '<div id="zbAS" class="zb-flex-col-bottom zb-flex-nowrap zb-width-r100">\
        <div id="zbASMask" class="zb-flex-grow1" onclick="{objName}.hide()"></div>\
        <div id="zbASBox" class="zb-flex-col-between zb-flex-stretch">\
          <div id="zbASTitle" class="zb-text-center"></div>\
          <div id="zbASBody" class="zb-scroll-y">\
            <div id="zbASSubBody"></div>\
          </div>\
          <div id="zbASFooter" class="zb-flex-row-around zb-flex-center">\
           <div class="zbASBtn" id="zbASBtnCancel" onclick="{objName}.hide()">取消</div>\
           <div class="zbASBtn" id="zbASBtnConfirm" onclick="{objName}.confirm()">确认</div>\
          </div>\
         </div>\
         <input type="hidden" id="zbInput" value="">\
        </div>';

    this.htmlToNode = function (html) {
        let div = document.createElement('div');
        div.innerHTML = html;
        return div.firstElementChild;
    }

    this.hide = function () {
        document.getElementById('zbAS').style.height = '0';
        document.getElementById('zbASSubBody').innerHTML = '';
        this.isConfirm = 0;
    }

    this.show = function () {
        document.getElementById('zbAS').style.height = '100%';
    }

    //点击确认按钮触发执行
    this.confirm = function () {
        if (this.isConfirm === 1) {
            console.log('重复点击');
            return;
        }
        this.isConfirm = 1;
        let value = document.getElementById('zbInput').value;
        this.hide();
        let obj = this.decodeObj(value);
        if (typeof this.onConfirm === 'function') {
            this.onConfirm(obj);
        }
    }

    //生成样式
    this.initCss = function() {
        let flag = document.getElementById('zbAS');
        if (flag == null) {
            let style = document.createElement('style');
            style.innerText =
                '.zb-flex-col-top {display:flex;flex-direction:column;justify-content:flex-start}'+
                '.zb-flex-col-bottom {display:flex;flex-direction:column;justify-content:flex-end}'+
                '.zb-flex-col-between {display:flex;flex-direction:column;justify-content:space-between}'+
                '.zb-flex-col-center {display:flex;flex-direction:column;justify-content:center}'+
                '.zb-flex-col-around {display:flex;flex-direction:column;justify-content:space-around}'+
                '.zb-flex-row-center {display:flex;flex-direction:row;justify-content:center}'+
                '.zb-flex-row-around {display:flex;flex-direction:row;justify-content:space-around}'+
                '.zb-flex-row-between {display:flex;flex-direction:row;justify-content:space-between}'+
                '.zb-flex-row-right {display:flex;flex-direction:row;justify-content:flex-end}'+
                '.zb-flex-stretch {align-items:stretch}'+
                '.zb-flex-center {align-items:center}'+
                '.zb-flex-grow1 {flex-grow:1}'+
                '.zb-flex-nowrap {flex-wrap:nowrap}'+
                '.zb-text-center {text-align:center}'+
                '.zb-scroll-x {overflow-x:scroll; white-space: nowrap;}'+
                '.zb-scroll-x::-webkit-scrollbar {display:none}'+
                '.zb-scroll-y {overflow-y:visible; white-space: nowrap;}'+
                '.zb-scroll-y::-webkit-scrollbar {display:none}'+
                '.zb-scroll{overflow:scroll; white-space: nowrap;}'+
                '.zb-scroll::-webkit-scrollbar {display:none}'+
                '.zb-width-r100{width:100%;}'+
                '.zb-height-r100{height:100%;}'+
                '#zbAS{position:fixed;top:0;height:0;z-index:200;overflow:hidden;background-color:rgba(0,0,0,0.4);}'+
                '#zbASMask{}'+
                '#zbASBox{max-height:90%;background-color:#fff;border-top-left-radius:10px;border-top-right-radius:10px;}'+
                '#zbASTitle{height:40px;line-height:40px;font-size:20px;border-bottom:1px solid #eeeeee;}'+
                '#zbASBody{min-height:100px;}'+
                //'#zbASSubBody{width:max-content; min-width:100%; min-height:100%;padding:3px;}'+
                '#zbASSubBody{min-height:100%;padding:3px;}'+
                '#zbASFooter{padding:5px;border-top:1px solid #eeeeee;height:40px;line-height:40px;}'+
                '.zbASBtn{width:50%;font-size:20px;text-align:center;}'+
                //'.zb-list{height:max-content;min-height:100%;flex-grow:1;flex-shrink:0;}'+
                '.zb-as-list{flex-grow:1;flex-shrink:0;}'+
                '.zb-as-list-item{margin:8px;height:30px;font-size:18px;text-align:center;flex-grow:1;flex-shrink:0;}'+
                '.zb-input{ height:30px;}'+
                '.zb-text{width:100%; max-width:100%; height:100%; min-height:100px; word-wrap:break-word;}'+
                '.zb-response{background-color:#eee}'+
                '.response {animation:bg_color 1s;}'+
                '@keyframes bg_color {from{background:#eee;} to{background:#fff;}}'+
                '@-webkit-keyframes bg_color {from{background:#eee;} to{background:#fff;}}'
            ;

            let head = document.getElementsByTagName('head')[0];
            head.appendChild(style);
        }
    }

    //创建html
    this.initTpl = function () {
        let flag = document.getElementById(this.instance);
        if (flag == null) {
            let body = document.getElementsByTagName('body')[0];
            this.tpl = this.tpl.replace(/\{objName\}/g, this.instance);
            let node = this.htmlToNode(this.tpl);
            body.appendChild(node);
        }
    }

    //添加纵向列表数据
    this.addList = function(data) {
        let tplList = '<div class="zb-as-list zb-flex-col-around overflow-y" id="{list_id}">{list_item}</div>';
        let tplListItem = '<div class="zb-as-list-item zb-flex-col-center" data-params="{params}" onclick="'+this.instance+'.changeListParams(this)">{name}</div>';

        let dataBody = document.getElementById('zbASSubBody');
        dataBody.classList.add('zb-flex-row-around');

        let listData = [];
        let arrListId = [];
        for (let i=0; i<data.length; i++) {
            let values = data[i]['values'];
            let params = data[i]['params']; //此参数内不能有name,value这俩参数，会被覆盖
            let listId = params['id'];

            if (listId) {
                //如果当前data中有重复的id只会加载一次
                if (arrListId.indexOf(listId) !== -1) {
                    continue;
                } else {
                    arrListId.push(listId);
                }

                //如果页面中已经存在id=listId的列表, 先删掉
                let element=document.getElementById(listId);
                if (element) {
                    console.log('已存在节点 #'+listId);
                    element.parentNode.removeChild(element);
                }
            }

            let listValues = [];
            if (this.isArray(values)) {
                //非键值对
                for (let i=0; i<values.length; i++) {
                    listValues.push({name: values[i], value:values[i]});
                }
            } else {
                //键值对
                for (let k in values) {
                    listValues.push({name:values[k], value:k});
                }
            }

            // 每一列的值
            let items = this.repeatString(tplListItem, listValues, function(row){
                let p = params;
                p['value'] = row['value'];
                p['name'] = row['name'];
                row['params'] = encodeURIComponent(JSON.stringify(p));

                return row;
            });

            listData.push({list_id:listId, list_item: items});
        }

        //组装每一列
        let listHtml = this.repeatString(tplList, listData);

        //追加到zbASSubBody中
        dataBody.innerHTML += listHtml;
    }

    //记录点击的list值
    this.changeListParams = function (obj) {
        document.getElementById('zbInput').value = obj.getAttribute('data-params');

        //清除其他高亮
        let list = document.getElementsByClassName('zb-response');
        for (let i = 0; i < list.length; i++) {
            list[i].classList.remove('zb-response');
        }

        //高亮当前选中
        obj.classList.add('zb-response');
    }

    //添加文字信息, 文本，日期，数字
    this.addInput = function (config) {
        //console.log(config);
        let box = document.getElementById('zbASSubBody');
        box.classList.add('zb-flex-col-center');
        box.classList.add('zb-flex-stretch');

        //初始化input标签
        let input = document.createElement('input');
        input.setAttribute('id', 'zb-input')
        for (let k in config['attr']) {
            if (k === 'id') {continue};
            input.setAttribute(k, config['attr'][k]);
        }

        input.setAttribute('data-params', this.encodeObj(config['params']));
        input.setAttribute('oninput', this.instance+'.changeTextParams(this)');
        input.classList.add('zb-input');
        box.appendChild(input);

        //初始化计数器
        let maxLength = config['attr']['maxlength'] ? config['attr']['maxlength'] : 0;
        if (maxLength > 0) {
            let defaultLength = config['attr']['value'] ? config['attr']['value']['length'] : 0;
            let tpl = '<div class="zb-flex-row-right"><div id="zb-text-length">'+defaultLength+'</div>/<div>'+maxLength+'</div></div>';
            let node = this.htmlToNode(tpl);
            box.appendChild(node);
        }
    }

    //添加文字信息, 可换行
    this.addTextarea = function (config) {
        document.getElementById('zbASBody').style.height = '500px';
        let box = document.getElementById('zbASSubBody');
        box.classList.add('zb-flex-col-center');
        box.classList.add('zb-flex-stretch');

        //初始化textarea标签
        let input = document.createElement('textarea');
        input.setAttribute('id', 'zb-textarea');
        for (let k in config['attr']) {
            if (k == 'id') {continue};
            input.setAttribute(k, config['attr'][k]);
        }
        input.setAttribute('data-params', this.encodeObj(config['params']));
        input.setAttribute('oninput', this.instance+'.changeTextParams(this)');
        input.setAttribute('style', 'height:450px')
        input.innerHTML = (config['value']) ? config['value'] : '';
        box.appendChild(input);

        //初始化计数器
        let maxLength = config['maxlength'] ? config['maxlength'] : 0;
        if (maxLength > 0) {
            let defaultLength = config['value'] ? config['value']['length'] : 0;
            let tpl = '<div class="zb-flex-row-right"><div id="zb-text-length">'+defaultLength+'</div>/<div>'+maxLength+'</div></div>';
            let node = this.htmlToNode(tpl);
            box.appendChild(node);
        }
    }

    //输入文本框时, 记录下输入的值, 并实时计算字数
    this.changeTextParams = function (obj){
        //变更长度
        let maxLength = obj.getAttribute('maxlength');
        if (maxLength) {
            let currLen = obj.value.length
            document.getElementById('zb-text-length').innerText = (currLen > maxLength) ? maxLength : currLen;
            if (currLen > maxLength) {
                obj.value = obj.value.substring(0, maxLength);
            }
        }

        //记录下输入的值
        let params = obj.getAttribute('data-params');
        let p = this.decodeObj(params);
        p['value'] = obj.value;
        document.getElementById('zbInput').value = this.encodeObj(p);
    }

    //根据数组, 渲染HTML字符串
    this.repeatString = function (tplDom, arr, func=null) {
        if (!tplDom.length) {
            this.error('字符串长度为空');
            return;
        }

        if (arr.length === 0) {
            this.error('数据为空');
            return tplDom;
        }

        let tpl = tplDom;
        let out = '';
        for (let i=0; i<arr.length; i++) {
            if (typeof func === 'function') {
                arr[i] = func(arr[i]);
            }
            let map = arr[i];
            let tmp = tpl;
            for (let j in map) {
                let re = new RegExp('{' + j + '}', 'g');
                tmp = tmp.replace(re, map[j]);
            }

            let re = new RegExp('{_idx}', 'g');
            tmp = tmp.replace(re, parseInt(i)+1);

            out += tmp;
        }

        return out;
    };

    //是否是数组
    this.isArray = function (o){
        return Object.prototype.toString.call(o) === '[object Array]';
    }

    this.error = function(str) {
        console.log(str);
    }

    this.encodeObj = function (obj) {
        return encodeURIComponent(JSON.stringify(obj));
    }

    this.decodeObj = function (str) {
        return JSON.parse(decodeURIComponent(str));
    }
}
/**
 * 用法举例:

 let zbAS = new zbActionSheet('zbAS');

 //弹窗编辑字段的值
 // module:编辑字段所属的模块名; id:数据库中的记录id; field:数据库中的字段名; defaultValue:当前值;
 // config: 当前编辑字段的配置信息， 包括字段注释（name）, 字段类型（data_type[list,string,number,date,text等]）, 步长（step）, 最大长度（maxlength）, 可选值列表（values）等
 // onConfirm: 点击确认后的回调方法, 没有则不触发回调
 let editField = function(module, id, field, defaultValue, config, onConfirm) {
    console.log(config);
    zbAS.init('zbAS', config.name);
    zbAS.onConfirm = onConfirm;
    let data_type = config.data_type;
    if (data_type === 'list') {
        let data = [{params: {id: field, field:field, module:module, module_id: id}, values: config.values}];
        zbAS.addList(data);
        zbAS.show();

    } else if (data_type === 'string') {
        let data = { attr:{id:field, type:'text', maxlength:config.maxlength, value:defaultValue}, params:{module:module,module_id:id,field:field}};
        zbAS.addInput(data);
        zbAS.show();

    } else if (data_type === 'number') {
        let data = {attr:{id:field, type:'number', step:config.step, maxlength:config.maxlength, value:defaultValue}, params:{module:module,module_id:id,field:field},};
        zbAS.addInput(data);
        zbAS.show();

    } else if (['date', 'datetime'].indexOf(data_type) !== -1) {
        let data = {attr:{id:field, type:data_type, value:defaultValue}, params:{module:module,module_id:id,field:field}};
        zbAS.addInput(data);
        zbAS.show();

    } else if (data_type === 'text') {
        let data = {attr:{id:field}, maxlength:config.maxlength, value:defaultValue, params:{module:module,module_id:id,field:field}};
        zbAS.addTextarea(data);
        zbAS.show();

    } else {
        nt.text('字段类型不支持');
    }
}
 */